﻿using System;
using System.Data;

namespace Dotnet.Utils.Utility.DataTableUtil
{
    public static class DataRowExtension
    {
        public static string TryParseToString(this DataRow dataRow, string name)
        {
            return dataRow.TryParseToClass<string>(name);
        }

        public static int? TryParseToInt32(this DataRow dataRow, string name)
        {
            int? num = dataRow.TryParseToStruct<int>(name);
            return num == int.MinValue ? null : num;
        }

        public static int TryParseToInt32(this DataRow dataRow, string name, int defaultValue)
        {
            int num = dataRow.TryParseToStructWithDefault(name, defaultValue);
            return num == int.MinValue ? defaultValue : num;
        }

        public static decimal? TryParseToDecimal(this DataRow dataRow, string name)
        {
            decimal? num = dataRow.TryParseToStruct<decimal>(name);
            return num == -2147483648m ? null : num;
        }

        public static decimal TryParseToDecimal(this DataRow dataRow, string name, decimal defaultValue)
        {
            decimal num = dataRow.TryParseToStructWithDefault(name, defaultValue);
            return num == -2147483648m ? defaultValue : num;
        }

        public static DateTime? TryParseToDateTime(this DataRow dataRow, string name)
        {
            DateTime? dateTime = dataRow.TryParseToStruct<DateTime>(name);
            return dateTime == NoneValue.NaDateTime ? null : dateTime;
        }

        public static DateTime TryParseToDateTime(this DataRow dataRow, string name, DateTime defaultValue)
        {
            DateTime dateTime = dataRow.TryParseToStructWithDefault(name, defaultValue);
            return dateTime == NoneValue.NaDateTime ? defaultValue : dateTime;
        }

        public static TEnum? TryParseToEnum<TEnum>(this DataRow dataRow, string name) where TEnum : struct
        {
            return dataRow.TryParseToStruct<TEnum>(name);
        }

        public static TEnum TryParseToEnum<TEnum>(this DataRow row, string name, TEnum defaultValue) where TEnum : struct
        {
            return row.TryParseToStructWithDefault(name, defaultValue);
        }

        private static T TryParseToClass<T>(this DataRow dataRow, string name) where T : class
        {
            T result;
            if (dataRow == null || !dataRow.Table.Columns.Contains(name))
            {
                result = default;
            }
            else
            {
                object obj = dataRow[name];
                if (obj == DBNull.Value)
                {
                    result = default;
                }
                else
                {
                    result = obj as T;
                }
            }
            return result;
        }

        private static T? TryParseToStruct<T>(this DataRow dataRow, string name) where T : struct
        {
            T? result;
            if (dataRow == null || !dataRow.Table.Columns.Contains(name))
            {
                result = null;
            }
            else
            {
                object obj = dataRow[name];
                if (obj == DBNull.Value)
                {
                    result = null;
                }
                else
                {
                    try
                    {
                        T value = (T)Convert.ChangeType(obj, typeof(T));
                        result = new T?(value);
                    }
                    catch (InvalidCastException)
                    {
                        result = null;
                    }
                }
            }
            return result;
        }

        private static T TryParseToStructWithDefault<T>(this DataRow dataRow, string name, T defaultValue = default) where T : struct
        {
            T result;
            if (dataRow == null || !dataRow.Table.Columns.Contains(name))
            {
                result = defaultValue;
            }
            else
            {
                object obj = dataRow[name];
                if (obj == DBNull.Value)
                {
                    result = defaultValue;
                }
                else
                {
                    try
                    {
                        T t = (T)Convert.ChangeType(obj, typeof(T));
                        result = t;
                    }
                    catch (InvalidCastException)
                    {
                        result = defaultValue;
                    }
                }
            }
            return result;
        }
    }
}